﻿/*
 * =====================================================================================
 *
 *    Description:  操作iis的类
 *
 *        Version:  1.1
 *        Created:  
 *       Revision:  none
 *       Compiler:  
 *
 *         Author:  imbedinlove@gmail.com
 *        Company:  
 *       EditTime:  2012年7月16日 15:54:51
 *         Update:  2014年10月23日 11:06:58
 * =====================================================================================

 | DateTime                | Revision Version | Describe         | Author                | Soft Version |
 | 2014年10月23日 11:12:26 | 1.1              | 删除全局临时域名 | imbedinlove@gmail.com | 1.1          |

 */
using System;
using System.Collections.Generic;
using System.Text;
using System.DirectoryServices;
using System.IO;
using System.Collections;
using System.Configuration;
using ICSharpCode.SharpZipLib.Zip;
using System.Security.AccessControl;
using WebSiteTools;
using ImbedLibrary;

namespace ImbedLibrary
{
    /// <summary>
    /// 委托
    /// </summary>
    /// <returns></returns>
    public delegate ArrayList GetPropertiesDelegate(DirectoryEntry ent);


    public class WebHelper
    {
        /// <summary>
        /// 配置站点
        /// </summary>
        /// <param name="hostName"></param>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        public static void RemoteConfig(String hostName, string userName, string password)
        {
            HostName = hostName;
            UserName = userName;
            Password = password;
        }
        private static string hostName = "localhost";
        private static string userName = "";
        private static string password = "";
        private static string ip = "*";

        public static string HostName
        {
            get
            {
                return hostName;
            }
            set
            {
                hostName = value;
            }
        }
        public static string UserName
        {
            get
            {
                return userName;
            }
            set
            {
                userName = value;
            }
        }
        public static string Password
        {
            get
            {
                return password;
            }
            set
            {
                if (UserName.Length <= 1)
                {
                    throw new ArgumentException("还没有指定好用户名。请先指定用户名");
                }
                password = value;
            }
        }

        /// <summary>
        /// 添加网站的方法
        /// </summary>
        /// <param name="hostIP">ip</param>
        /// <param name="portNum">端口</param>
        /// <param name="descOfWebSite">域名</param>
        /// <param name="commentOfWebSite">站名</param>
        /// <param name="webPath">物理路径</param>
        /// <param name="userName">用户名</param>
        /// <param name="userPwd">用户密码</param>
        /// <returns>创建信息</returns>
        public static string CreateNewWebSite(string hostIP, string portNum, string descOfWebSite, string commentOfWebSite, string webPath, string userName, string userPwd)
        {
            string Messag = "ok";

            try
            {
                DirectoryEntry rootEntry = GetEnt();//取得iis路径
                string newSiteNum = GetNewWebSiteID(); //取得新网站ID
                DirectoryEntry newSiteEntry = rootEntry.Children.Add(newSiteNum, "IIsWebServer"); //增加站点
                newSiteEntry.CommitChanges();//保存对区域的更改(这里对站点的更改)

                rootEntry.CommitChanges();//保存设置

                newSiteEntry.Properties["ServerBindings"].Value = descOfWebSite;
                newSiteEntry.Properties["ServerComment"].Value = commentOfWebSite;//站名
                newSiteEntry.Properties["AnonymousUserName"].Value = userName;//站点用户名
                newSiteEntry.Properties["AnonymousUserPass"].Value = userPwd;//站点密码
                newSiteEntry.Properties["ServerBindings"].Value = hostIP + ":" + portNum + ":" + descOfWebSite;//设置，ip，端口，主机头


                newSiteEntry.CommitChanges();
                DirectoryEntry vdEntry = newSiteEntry.Children.Add("root", "IIsWebVirtualDir");

                vdEntry.Properties["Path"].Value = webPath;//设置物理路径
                vdEntry.Properties["AppFriendlyName"].Value = commentOfWebSite;//设置应用程序名
                //vdEntry.Invoke("AppCreate", true);//创建应用程序
                vdEntry.Properties["AspEnableParentPaths"].Value = true;//启用父路径
                vdEntry.Properties["AccessRead"][0] = true;//站点读取权限
                string appPoolId = GetAppPoolId();
                Logs.Note("AppPoolId:" + appPoolId);
                vdEntry.Properties["AppPoolId"].Value = appPoolId;//应用池
                vdEntry.Properties["AccessScript"][0] = true;//执行权限 脚本

                vdEntry.CommitChanges();
            }
            catch (Exception)
            {
                throw;
            }
            return Messag;
        }

        /// <summary>
        /// 获取应用池名称
        /// </summary>
        /// <returns></returns>
        public static string GetAppPoolId()
        {
            DirectoryEntry w3svc = new DirectoryEntry("IIS://localhost/W3SVC/AppPools");
            foreach (DirectoryEntry entry2 in w3svc.Children)
            {
                string path = "IIS://localhost/W3SVC/AppPools/" + entry2.Name;
                DirectoryEntry de = new DirectoryEntry(path);
                object[] s = de.Invoke("EnumAppsInPool", null) as object[];
                if (s.Length < 20)
                    return entry2.Name;
            }
            return "Z";
        }

        /// <summary>
        /// 网站是否存在
        /// </summary>
        /// <param name="webName">站名</param>
        /// <returns></returns>
        public static bool Exists(String webName)
        {
            try
            {
                DirectoryEntry ent = GetEnt();
                foreach (DirectoryEntry child in ent.Children)
                {
                    if (child.SchemaClassName == "IIsWebServer")
                    {
                        if (child.Properties["ServerBindings"].Value != null)
                        {
                            if (child.Properties["ServerComment"].Value.ToString() == webName)
                            {
                                return true;
                            }
                        }
                    }
                }
            }
            catch (Exception)
            {

                throw;
            }
            return false;
        }

        /// <summary>
        /// 查找网站
        /// </summary>
        /// <param name="commentOfWebSite">站名</param>
        /// <returns>创建信息</returns>
        public static DirectoryEntry SelectWebSite(string commentOfWebSite)
        {
            try
            {
                DirectoryEntry ent = GetEnt();
                foreach (DirectoryEntry child in ent.Children)
                {
                    if (child.SchemaClassName == "IIsWebServer")
                    {
                        if (child.Properties["ServerBindings"].Value != null)
                        {
                            if (child.Properties["ServerComment"].Value.ToString() == commentOfWebSite)
                            {
                                return child;
                            }
                        }
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }
            return null;
        }

        /// <summary>
        /// 修改站点域名
        /// </summary>
        /// <param name="hostIP">ip</param>
        /// <param name="portNum">端口</param>
        /// <param name="domain">域名</param>
        /// <param name="webName">站名</param>
        /// <param name="Messag"></param>
        /// <param name="returnMeg"></param>
        /// <returns></returns>
        public static string ChangeWebSite(string hostIP, string portNum, string domain, string webName)
        {
            DirectoryEntry child = SelectWebSite(webName);
            if (child == null)
                return "未找到站点：" + webName;
            child.Properties["ServerBindings"].Value = hostIP + ":" + portNum + ":" + domain;//设置，ip，端口，主机头
            child.Properties["ServerBindings"].Add(hostIP + ":" + portNum + ":" + domain.Replace("www.", ""));
            child.CommitChanges();
            Logs.Note("完成," + webName + "," + domain);
            return "ok";
        }

        /// <summary>
        /// 追加站点域名
        /// </summary>
        /// <param name="hostIP">ip</param>
        /// <param name="portNum">端口</param>
        /// <param name="domain">域名</param>
        /// <param name="webName">站名</param>
        /// <param name="Messag"></param>
        /// <param name="returnMeg"></param>
        /// <returns></returns>
        public static string AddDomain(string hostIP, string portNum, string domain, string webName)
        {
            try
            {
                DirectoryEntry child = SelectWebSite(webName);
                if (child == null)
                {
                    Logs.Note("未找到站点[" + webName + "]");
                    return "未找到站点：" + webName;
                }
                String bindings = hostIP + ":" + portNum + ":" + domain;
                if (child.Properties["ServerBindings"].Value.GetType().Name == "String")
                {
                    child.Properties["ServerBindings"].Add(bindings);
                }
                else
                {
                    Object[] t = child.Properties["ServerBindings"].Value as Object[];
                    if (t.Length != 0)
                    {
                        for (int l = 0; l < t.Length; l++)
                        {
                            if (bindings == t[l].ToString())
                                break;
                            if ((l + 1) == t.Length)
                                child.Properties["ServerBindings"].Add(bindings);
                        }
                    }
                }
                child.CommitChanges();
            }
            catch (Exception)
            {
                throw;
            }
            return "ok";
        }

        /// <summary>
        /// 验证站点配置是否和数据库相同
        /// </summary>
        /// <param name="hostIP">ip</param>
        /// <param name="portNum">端口</param>
        /// <param name="descOfWebSite">域名</param>
        /// <param name="commentOfWebSite">站名</param>
        /// <returns>创建信息</returns>
        public static string CheckingWebSite(string hostIP, string portNum, string descOfWebSite, string commentOfWebSite)
        {
            string Messag = "失败,服务器上未找到站点";
            try
            {
                string DomainOk = DomainFormat(descOfWebSite);
                string entPath = String.Format("IIS://{0}/w3svc", HostName);
                DirectoryEntry ent = GetDirectoryEntry(entPath);
                foreach (DirectoryEntry child in ent.Children)
                {
                    if (child.SchemaClassName == "IIsWebServer")
                    {
                        if (child.Properties["ServerBindings"].Value != null)
                        {
                            if (child.Properties["ServerComment"].Value.ToString() == commentOfWebSite)
                            {
                                //child.Properties["ServerBindings"].Value = hostIP + ":" + portNum + ":" + descOfWebSite;//设置，ip，端口，主机头
                                //child.Properties["ServerBindings"].Add(hostIP + ":" + portNum + ":" + descOfWebSite.Replace("www.", ""));
                                //child.CommitChanges();
                                int count = child.Properties["ServerBindings"].Count;
                                Messag = "";
                                for (int i = 0; i < count; i++)
                                {
                                    Messag += child.Properties["ServerBindings"][i].ToString() + "\r\n";
                                }
                                Console.Write(Messag);
                            }
                        }
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
            }
            return Messag;
        }

        /// <summary>
        /// 确定一个新的网站与现有的网站没有相同的。
        /// 这样防止将非法的数据存放到IIS里面去
        /// </summary>
        /// <param name="bindStr">网站邦定信息</param>
        /// <returns>真为可以创建，假为不可以创建</returns>
        public static bool EnsureNewSiteEnavaible(string bindStr)
        {
            string entPath = String.Format("IIS://{0}/w3svc", HostName);
            try
            {
                DirectoryEntry ent = GetDirectoryEntry(entPath);
                foreach (DirectoryEntry child in ent.Children)
                {
                    if (child.SchemaClassName == "IIsWebServer")
                    {
                        if (child.Properties["ServerBindings"].Value != null)
                        {
                            if (child.Properties["ServerBindings"].Value.ToString() == bindStr)
                            {
                                return false;
                            }
                        }
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }
            return true;
        }

        /// <summary>
        /// 根据是否有用户名来判断是否是远程服务器。
        /// 然后再构造出不同的DirectoryEntry出来
        /// </summary>
        /// <param name="entPath">DirectoryEntry的路径</param>
        /// <returns>返回的是DirectoryEntry实例</returns>
        public static DirectoryEntry GetDirectoryEntry(string entPath)
        {
            DirectoryEntry ent;
            if (UserName == null || userName == "")
            {
                ent = new DirectoryEntry(entPath);
            }
            else
            {
                ent = new DirectoryEntry(entPath, HostName + "\\" + UserName, Password, AuthenticationTypes.Secure);
                //ent = new DirectoryEntry(entPath, UserName, Password, AuthenticationTypes.Secure);
            }
            return ent;
        }

        /// <summary>
        /// GetEntPath
        /// </summary>
        /// <returns></returns>
        public static String GetEntPath()
        {
            return String.Format("IIS://{0}/w3svc", HostName);
        }

        /// <summary>
        /// GetEnt
        /// </summary>
        /// <returns></returns>
        public static DirectoryEntry GetEnt()
        {
            return GetDirectoryEntry(GetEntPath());
        }

        /// <summary>
        /// GetAllWebNameDelegate
        /// </summary>
        /// <returns></returns>
        private static ArrayList GetAllWebNameDelegate(DirectoryEntry ent)
        {
            ArrayList name = new ArrayList();
            name.Add(ent.Properties["ServerComment"].Value);
            return name;
        }

        /// <summary>
        /// 获取IIS所有网站的物理路径 (委托)
        /// </summary>
        /// <param name="ent">IIS</param>
        /// <returns>物理路径</returns>
        private static ArrayList GetAllSitePathDelegate(DirectoryEntry ent)
        {
            ArrayList path = new ArrayList();
            path.Add(ent.Properties["Path"].Value);
            return path;
        }

        /// <summary>
        /// GetAllWebName
        /// </summary>
        public static IList<ArrayList> GetAllWebName()
        {
            return GetEntChildernProperties(GetAllWebNameDelegate);
        }

        /// <summary>
        /// 获取IIS所有网站的物理路径
        /// </summary>
        /// <returns>物理路径</returns>
        public static IList<ArrayList> GetAllSitePath()
        {
            return GetEntChildernProperties(GetAllSitePathDelegate);
        }

        /// <summary>
        /// GetEntChildernProperties
        /// 异常:
        ///     MemberAccessException: 无权操作iis
        /// </summary>
        /// <param name="getProperties"></param>
        /// <returns></returns>
        public static IList<ArrayList> GetEntChildernProperties(GetPropertiesDelegate getProperties)
        {
            if(!ImbedLibrary.GetHelper.IsAdministrator())
            {
                throw new MemberAccessException("E04301:访问权限必须是管理员,否则无权操作IIS");
            }
            DirectoryEntry ent = GetEnt();
            IList<ArrayList> propertieList = new List<ArrayList>();
            foreach (DirectoryEntry child in ent.Children)
            {
                if (child.SchemaClassName == "IIsWebServer")
                {
                    propertieList.Add(getProperties(child));
                }
            }
            return propertieList.Count == 0 ? null : propertieList;
        }

        /// <summary>
        /// GetWebCount
        /// </summary>
        /// <returns></returns>
        public static String GetWebCount()
        {
            DirectoryEntry ent = GetEnt();
            String tmpStr = String.Empty;
            ArrayList list = new ArrayList();
            foreach (DirectoryEntry child in ent.Children)
            {
                if (child.SchemaClassName == "IIsWebServer")
                {
                    tmpStr = child.Name.ToString();
                    list.Add(Convert.ToInt32(tmpStr));
                }
            }
            return list.Count.ToString();
        }

        /// <summary>
        /// 获取网站系统里面可以使用的最小的ID。
        /// 这是因为每个网站都需要有一个唯一的编号，而且这个编号越小越好。
        /// 这里面的算法经过了测试是没有问题的。
        /// </summary>
        /// <returns>最小的id</returns>
        public static string GetNewWebSiteID()
        {
            ArrayList list = new ArrayList();
            String tmpStr;
            String entPath = GetEntPath();
            DirectoryEntry ent = GetDirectoryEntry(entPath);
            foreach (DirectoryEntry child in ent.Children)
            {
                if (child.SchemaClassName == "IIsWebServer")
                {
                    tmpStr = child.Name.ToString();
                    list.Add(Convert.ToInt32(tmpStr));
                }
            }
            list.Sort();
            int i = 1;
            foreach (int j in list)
            {
                if (i == j)
                {
                    i++;
                }
            }
            return i.ToString();
        }

        /// <summary>
        /// 配置站点
        /// </summary>
        /// <param name="webSiteName">站名</param>
        /// <param name="domain">域名</param>
        /// <param name="templatesName">模板名</param>
        /// <param name="filesOk">文件夹是否存在,不存在则创建</param>
        /// <param name="ftpOk">ftp是否存在,不存在则创建</param>
        /// <param name="port">端口</param>
        /// <returns></returns>
        public static string CreateWebSite(string webSiteName, string domain, string templatesName, bool filesOk, bool ftpOk, string port)
        {
            //站名简拼,             记录信息,     网站域名, 网站路径      ,  模板路径,         ftp消息,        临时域名
            string siteNameJianPin, message = "", DomainOk, webSitePath = "", templatePath = "", ftpMes = "", tempDomain = "";
            siteNameJianPin = PinYin.Convert(webSiteName);                            //转换站名简拼
            tempDomain = GetTools.AppConfig("tempDomain");
            try
            {
                if (templatesName != "")
                {
                    templatePath = GetTools.AppConfig("templatePath") + templatesName.Trim() + ".zip";
                    if (!File.Exists(templatePath))
                        return "TemplatesName:" + templatePath + ".没有模板文件";
                }
                //创建用户
                UserConfig.CreateLocalUserAccount(siteNameJianPin, "!QAZ1qaz", webSiteName);
                //去掉 3w .com .cn .gov
                DomainOk = DomainFormat(domain);

                webSitePath = GetTools.WebsitePath(siteNameJianPin) + DomainOk;
                if (filesOk == true)
                    FolderTools.SetFolderACL(webSitePath, siteNameJianPin, FileSystemRights.Write | FileSystemRights.Read, AccessControlType.Allow);
                else
                    FolderTools.CreateFolder(webSitePath, siteNameJianPin);

                RemoteConfig("localhost", @"SCJG-SERVER\" + siteNameJianPin, "!QAZ1qaz");
                if (templatesName != "")
                    (new FastZip()).ExtractZip(templatePath, webSitePath, "");

                if (ftpOk == false)
                    FtpTools.AddServUser(DomainFormatServU(domain), DomainOk + "!@#", GetTools.AppConfig("seruPath"), webSitePath);

                message = CreateNewWebSite(ip, port, DomainOk + tempDomain, siteNameJianPin.Remove(1) + webSiteName, webSitePath, siteNameJianPin, "!QAZ1qaz")
                    + "\r\n"
                    + "CreateServ-u:" + ftpMes + "\r\n"
                    + "SiteName:" + siteNameJianPin.Remove(1) + webSiteName + "\r\n"
                    + "WindowsUser:" + siteNameJianPin + "\r\n"
                    + "WindowsPwd:!QAZ1qaz\r\n"
                    + "FTPUser:" + DomainFormatServU(domain) + "\r\n"
                    + "FTPPwd:" + DomainOk + "!@#\r\n"
                    + "WebPath:" + webSitePath + "\r\n"
                    + "TempDomain:" + DomainOk + tempDomain + "\r\n"
                    + "JianPin:" + siteNameJianPin + "\r\n"
                    + "Domain:" + domain;
                Logs.Note(message);
                return "ok";
            }
            catch (Exception e)
            {
                return ErrorMessageTools.logErr(e);
            }
            finally
            {
                FileStream fs = new FileStream(GetTools.EventPath() + webSiteName + DateTime.Now.ToString("yyMMddhhmmss") + ".txt", FileMode.OpenOrCreate);
                StreamWriter sw = new StreamWriter(fs);

                sw.Write(message);
                sw.Flush();
                sw.Close();
                sw.Dispose();
                fs.Dispose();
                fs.Close();
            }
        }

        /// <summary>
        /// 去掉 3w .com .cn .gov
        /// </summary>
        /// <param name="Domain"></param>
        /// <returns></returns>
        public static string DomainFormat(string Domain)
        {
            string DomainOk = Domain;
            if (DomainOk.IndexOf("www.") == 0)
            {
                DomainOk = DomainOk.Replace("www.", "");
            }
            if (DomainOk.Contains(".cn"))
            {
                DomainOk = DomainOk.Replace(".cn", "");
            }
            if (DomainOk.Contains(".gov"))
            {
                DomainOk = DomainOk.Replace(".gov", "");
            }
            if (DomainOk.Contains(".com"))
            {
                DomainOk = DomainOk.Replace(".com", "");
            }
            if (DomainOk.Contains(".org"))
            {
                DomainOk = DomainOk.Replace(".org", "");
            }
            return DomainOk;
        }

        /// <summary>
        /// 把网站域名更改为serv-u帐号
        /// </summary>
        /// <param name="Domain"></param>
        /// <returns></returns>
        private static string DomainFormatServU(string Domain)
        {
            string DomainOk = Domain;
            if (DomainOk.IndexOf("www.") == 0)
            {
                DomainOk = DomainOk.Replace("www.", "");
            }
            if (DomainOk.Contains("."))
            {
                DomainOk = DomainOk.Replace(".", "_");
            }
            return DomainOk;
        }
    }
}
